home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-02 | 2.8 KB | 124 lines | [TEXT/MSET] |
- \ UNDO - mrh Aug 94
-
- (*
- This file is a first try at implementing a generic UNDO facility. The
- concept is actually quite simple, but it should allow just about any kind
- of UNDO you might want.
- There is a handleList UNDO_LIST. Each object in this list undoes some
- action. Here's the way you set things up:
-
- 1. Subclass UNDOABLE_ACTION for each kind of action you want to be
- undoable. See the example at the end for how we do this for window
- resizing (not all that useful, but who cares, it's an example).
-
- 2. Each such subclass should have an INIT: method that saves whatever
- info it needs to do an undo of that action. The object on which the
- action to be performed will be pointed to by the ptr MyObject.
- This method must start by calling init: super, which will set up MyObject.
-
- 3. The subclass should also have an UNDO: method that uses the saved info
- to undo the action. Again the target object will pointed to by MyObject,
- so you should send late-bound messages to whatever MyObject points to.
-
- 4. Your class whose objects are to have undoable actions on them, needs
- the appropriate methods to begin with
- ['] <undoable-action-class> make_undoable
-
- That's it.
-
- See the example for how to do it.
-
- A fuller implementation of this idea would have some way to update undo_list
- if an object with outstanding undoable actions is deleted.
-
- *)
-
-
- need window+ \ just for the example, actually
-
-
- :class UNDOABLE_ACTION super{ object }
-
- ptr myObject
-
- :m SET_OBJECT: ( ^obj -- ) put: myObject ;m
-
- :m INIT: put: myObject ;m
-
- :m UNDO: ;m \ should be overridden!
-
- ;class
-
-
- \ UNDO_LIST_CLASS is a one-off class for implementing UNDO_LIST. Of course,
- \ I guess you might want multiple undo lists. Be my guest.
-
- :class UNDO_LIST_CLASS super{ handleList }
-
- var MAX_UNDOS
-
- :m SETMAX: put: max_undos ;m
-
- :m NEWOBJ: \ Overriding NewObj: on handleList. If we're at the
- \ max limit, we delete the first item.
-
- size: self get: max_undos >=
- IF 0 select: self remove: self
- THEN
- newObj: super ;m
-
- :m CLASSINIT: 100 put: max_undos ;m
-
- ;class
-
-
- undo_list_class UNDO_LIST
-
-
- : UNDO { \ index -- }
- size: undo_list 0EXIT
- selectLast: undo_list
- current: undo_list -> index
- obj: undo_list undo: []
- index select: undo_list \ Sending undo: probably added a
- \ new element to the end
- remove: undo_list ; \ Finished with this one, so delete it
-
-
- : MAKE_UNDOABLE \ ( ^undoable_action_subclass -- )
- newObj: undo_list
- ^base obj: undo_list init: [] unlock: undo_list ;
-
-
- \ endload
-
-
- :class uWindSize super{ undoable_action }
-
- rect oldRect
-
- :m INIT: ( ^wind-obj -- )
- init: super
- get: myObject getRect: [] put: oldRect ;m
-
- :m UNDO:
- getBot: oldRect get: myObject size: [] ;m
-
- ;class
-
-
- :class uWindow super{ window+ }
-
- :m SIZE: ( x y -- )
- ['] uWindSize make_undoable
- size: super ;m
-
- ;class
-
-
- uWindow WW
- view VV
-
- : GO 4 setmax: undo_list
- vv test: ww ;
-